/*
	Copyright (C) 2014 Salil Bhagurkar

	This file is part of illusion

	illusion is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	illusion is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with illusion.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <arch/console.h>
#include <arch/portio.h>
#include <arch/power.h>
#include <kernel/console.h>
#include <kernel/config.h>
#include <kernel/errors.h>
#include <klib/lib.h>

//
// File Visibility: ARCH
// Subsystem: ARCH/CONSOLE
// File Description: Console (text output) implementation by the platform.
//

struct console_driver x86_boot_console_driver;

static int update_hardware_cursor()
{
	int total_cursor = x86_boot_console_driver.cursor_y * 80 +
			x86_boot_console_driver.cursor_x;
	outb(0x3d4, 15);
	outb(0x3d5,(u8)total_cursor);
	outb(0x3d4, 14);
	outb(0x3d5,(u8)(total_cursor >> 8));
	return ENONE;
}


static int update_buffer(uint_t start_x, uint_t start_y, uint_t width, uint_t height)
{
	uint_t x, y;
	char *video_mem = (char *)0xb8000;
	uint_t max_y = (start_y + height);
	uint_t max_x = (start_x + width);

	if(max_y > 25 || max_x > 80)
		return EPARAM;

	for(y = start_y; y < (max_y); y++) {
		for(x = start_x; x < (max_x); x++) {
			uint_t index = y * 160 + x * 2, buf_index = y * 80 + x;
			video_mem[index] =
				x86_boot_console_driver.buffer[buf_index];
		}
	}
	return ENONE;
}

static int init()
{
	x86_boot_console_driver.height = 25;
	x86_boot_console_driver.width = 80;
	return ENONE;
}

static char conbuf[2000];

struct console_driver x86_boot_console_driver = {
		.update_buffer = update_buffer,
		.update_hardware_cursor = update_hardware_cursor,
		.update_size = (void *)device_dummy,
		.init = init,
		.buffer = conbuf,
		.active = 1,
		.flags = CONSOLE_BUFFERED,
		.cursor_x = 0,
		.cursor_y = 0,
		.write = device_dummy,
		.next = null,
		.prev = null
};
